// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.asm.analysis;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicInterpreter;
import org.objectweb.asm.tree.analysis.Value;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public final class LocalsInterpreter extends InterpreterAdapter {
  public LocalsInterpreter() {
    super(new BasicInterpreter());
  }

  @Override
  public Value copyOperation(AbstractInsnNode insn, Value value) throws AnalyzerException {
    switch (insn.getOpcode()) {
      case Opcodes.ALOAD:
      case Opcodes.ILOAD:
      case Opcodes.LLOAD:
        return new LocalsValue(1, ((VarInsnNode) insn).var);
      case Opcodes.FLOAD:
      case Opcodes.DLOAD:
        return new LocalsValue(2, ((VarInsnNode) insn).var);
    }
    return super.copyOperation(insn, value);
  }

  @Override
  public Value merge(Value v, Value w) {
    if (getVar(v) == getVar(w)) {
      return v;
    } else {
      return super.merge(v, w);
    }
  }

  public static int getVar(Value value) {
    if (value instanceof LocalsValue) {
      return ((LocalsValue) value).getVar();
    } else {
      return -1;
    }
  }

  private static final class LocalsValue implements Value {
    private final int size;
    private final int var;

    public LocalsValue(int size, int var) {
      this.size = size;
      this.var = var;
    }
    
    public int getSize() {
      return size;
    }
    
    public int getVar() {
      return var;
    }
  }
}
